package com.base.app_core.View.xrecyclerview;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.base.app_core.base.impl.BaseViewHolder;
import com.base.app_core.util.XYBAUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by xiangheng.song on 2017/3/3.
 */

public abstract class RecyclerAdapter<T, V extends RecyclerViewHolder> extends RecyclerView.Adapter<V> {

    private static final Map<Class<?>, Constructor<? extends BaseViewHolder>> VIEW_HOLDER_MAPPING = new HashMap<>();
    private static final Set<Class> INNER_CLASS_SET = new HashSet<>();

    protected List<T> list = new LinkedList<>();

    public List<T> getList() {
        return list;
    }

    @Override
    public V onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(getItemLayoutId(), parent, false);
//		View view = View.inflate(parent.getContext(), getItemLayoutId(), null);
        return (V) createViewHolder(this, view);
    }

    public T getObject(int i) {
        return list.get(i);
    }

    @Override
    public void onBindViewHolder(V holder, int position) {
        fillData(getObject(position), holder);
    }

    protected abstract void fillData(T item, V holder);

    protected abstract int getItemLayoutId();

    @Override
    public int getItemCount() {
        return list.size();
    }

    public void addAll(List<T> data) {
        list.addAll(data);
    }

    public void clear() {
        list.clear();
    }

    public void notifyDataSetChanged(List<T> data) {
        if (XYBAUtils.isEmpty(data)) {
            return;
        }
        list.clear();
        list.addAll(data);
        notifyDataSetChanged();
    }

    private static Object createViewHolder(RecyclerAdapter adapter, View view) {
        Class<?> adapterClass = adapter.getClass();
        Constructor constructor = VIEW_HOLDER_MAPPING.get(adapterClass);
        boolean isInnerClass = INNER_CLASS_SET.contains(adapterClass);
        if (constructor == null) {
            try {
                Class<?> viewHolderClass = (Class<?>) ((ParameterizedType) adapterClass.getGenericSuperclass()).getActualTypeArguments()[1];
                isInnerClass = viewHolderClass.getName().contains("$");
                if (isInnerClass) {
                    // 内部类构造方法第一个参数是外部类的对象
                    constructor = viewHolderClass.getConstructor(adapter.getClass(), View.class);
                    INNER_CLASS_SET.add(adapterClass);
                } else {
                    constructor = viewHolderClass.getConstructor(View.class);
                }
                VIEW_HOLDER_MAPPING.put(adapterClass, constructor);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            if (isInnerClass) {
                return constructor.newInstance(adapter, view);
            }
            return constructor.newInstance(view);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
